#ifndef SLIDING_H
#define SLIDING_H

#include <stddef.h>

#define SAMPLE_PERIOD         0.002f
#define V_EORROR_INTEGRAL_MAX 2000.0f
#define P_EORROR_INTEGRAL_MAX 2000.0f

typedef enum
{
    EXPONENT,  // 线性滑模面，指数趋近率
    POWER,     // 线性滑模面，幂次趋近率
    TFSMC,     // 快速终端滑模控制
    VELSMC,    // 比例积分滑模面，指数趋近律，速度控制
    EISMC      // 比例积分滑模面，指数趋近律，位置控制
} Rmode;

typedef struct
{
    float tar_now;                  // 当前目标值
    float tar_last;                 // 上一次目标值
    float tar_differential;         // 目标值一阶导
    float tar_differential_last;    // 上一次目标值一阶导
    float tar_differential_second;  // 目标值二阶导

    float pos_get;  // 当前位置
    float vol_get;  // 当前速度

    float p_error;  // 位置误差
    float v_error;  // 速度误差（位置误差一阶导）

    float p_error_integral;  // 位置误差积分
    float v_error_integral;  // 速度误差积分

    float pos_error_eps;  // 误差精度
    float vol_error_eps;  // 误差精度
    float error_last;
} RError;

typedef struct
{
    float J;
    float K;
    float c;

    float c1;  // EIsmc参数
    float c2;  // EIsmc参数

    float p;        // tfsmc参数，正奇数 p>q
    float q;        // tfsmc参数，正奇数
    float beta;     // tfsmc参数，正数
    float epsilon;  // ε噪声上限
} SlidingParam;

typedef struct
{
    float u;  // 控制器输出
    float s;  // 滑模面计算储存

    SlidingParam param;
    SlidingParam param_last;

    RError error;
    float u_max;  // 输出限幅
    Rmode flag;   // 符号和饱和切换，未用到
    float limit;  // 饱和函数上下限
} cSMC;

void SMC_Init(cSMC* self);
void SMC_SetParamExp(cSMC* self, float J, float K, float c, float epsilon, float limit, float u_max, Rmode flag,
                     float pos_esp);  // 滑膜参数设定 EXPONENT,POWER,VELSMC 参数
void SMC_SetParamTFSMC(cSMC* self, float J, float K, float p, float q, float beta, float epsilon, float limit,
                       float u_max, Rmode flag, float pos_esp);  // 滑膜参数设定 TFSMC 参数
void SMC_SetParamEISMC(cSMC* self, float J, float K, float c1, float c2, float epsilon, float limit, float u_max,
                       Rmode flag,
                       float pos_esp);  /// EISMC 参数设定
void SMC_ErrorUpdatePos(cSMC* self, float target, float pos_now,
                        float vol_now);  // 滑膜位置误差更新
void SMC_ErrorUpdateVel(cSMC* self, float target,
                        float vol_now);  // 滑模速度误差更新
void SMC_Clear(cSMC* self);
void SMC_Integval_Clear(cSMC* self);
float SMC_Calculate(cSMC* self);  // 滑模控制器计算函数
float SMC_Out(cSMC* self);
void SMC_SetOut(cSMC* self, float out);

#endif  // SLIDING_H
